#include <string.h>
#include "4G_mqtt.h"
#include <stdio.h>
#include <stdarg.h>


static int sendf(ml307g_t *h, const char *fmt, ...) {
    char buf[256];
    va_list ap;
    va_start(ap, fmt);
    int n = vsnprintf(buf, sizeof(buf), fmt, ap);
    va_end(ap);
    if (n < 0) return -1;
    if ((size_t) n > sizeof(buf)) n = sizeof(buf);
    return h->write((const uint8_t *) buf, (size_t) n);
}


void ml307g_init(ml307g_t *h, ml307g_uart_write_fn wr, ml307g_millis_fn ms, ml307g_delay_ms_fn d) {
    memset(h, 0, sizeof(*h));
    h->write = wr;
    h->millis = ms;
    h->delay_ms = d;
}


// ---- 工具：等待 OK/ERROR 或目标前缀（简化，生产可用信号量/事件替换）
static int wait_for(ml307g_t *h, uint32_t timeout_ms, const char *ok1, const char *ok2) {
    uint32_t t0 = h->millis();
    for (;;) {
        // 在外部串口中断里持续调用 ml307g_feed_byte 来填充 h->line
        if (strstr(h->line, ok1) || (ok2 && strstr(h->line, ok2))) return 0;
        if (strstr(h->line, "ERROR") || strstr(h->line, "+CME ERROR")) return -1;
        if ((h->millis() - t0) > timeout_ms) return -2;
        h->delay_ms(10);
    }
}


int ml307g_modem_basic(ml307g_t *h) {
    sendf(h, "AT\r");
    if (wait_for(h, 1000, "OK", NULL)) return -1;
    sendf(h, "ATE0\r");
    if (wait_for(h, 1000, "OK", NULL)) return -2;
    // 注册、附着（不同厂商可能指令不同，此处给出常见命令占位）
    sendf(h, "AT+CREG?\r");
    wait_for(h, 2000, "+CREG:", "OK");
    sendf(h, "AT+CGATT=1\r");
    if (wait_for(h, 5000, "OK", NULL)) return -3;
    return 0;
}


int ml307g_set_apn(ml307g_t *h, const ml307g_pdp_cfg_t *pdp) {
    // 以 cid=1 举例；具体命令以 ML307G 文档为准
    sendf(h, "AT+CGDCONT=1,\"IP\",\"%s\"\r", pdp->apn ? pdp->apn : "");
    if (wait_for(h, 1000, "OK", NULL)) return -1;
    if (pdp->user && *pdp->user) {
        sendf(h, "AT+QICSGP=1,1,\"%s\",\"%s\",1\r", pdp->user, pdp->pwd ? pdp->pwd : "");
        if (wait_for(h, 1000, "OK", NULL)) return -2;
    }
    return 0;
}


int ml307g_pdp_activate(ml307g_t *h, int cid) {
    sendf(h, "AT+CGACT=1,%d\r", cid);
    if (wait_for(h, 6000, "OK", NULL)) return -1;
    h->linked = 1;
    return 0;
}


int ml307g_mqtt_cfg(ml307g_t *h, const ml307g_mqtt_cfg_t *cfg) {
    h->mqtt = *cfg;
    // 依据《MQTT用户手册》：AT+MQTTCFG=参数项，示例：版本/保活/clean/用户名/密码/ClientID 等
    if (cfg->version) {
        sendf(h, "AT+MQTTCFG=\"version\",%d,%d\r", cfg->connect_id, cfg->version);
        wait_for(h, 1000, "OK", NULL);
    }
    if (cfg->keepalive_s) {
        sendf(h, "AT+MQTTCFG=\"keepalive\",%d,%d\r", cfg->connect_id, cfg->keepalive_s);
        wait_for(h, 1000, "OK", NULL);
    }
    sendf(h, "AT+MQTTCFG=\"clean\",%d,%d\r", cfg->connect_id, cfg->clean_session ? 1 : 0);
    wait_for(h, 1000, "OK", NULL);
    if (cfg->client_id) {
        sendf(h, "AT+MQTTCFG=\"clientid\",%d,\"%s\"\r", cfg->connect_id, cfg->client_id);
        wait_for(h, 1000, "OK", NULL);
    }
    if (cfg->username) {
        sendf(h, "AT+MQTTCFG=\"user\",%d,\"%s\"\r", cfg->connect_id, cfg->username);
        wait_for(h, 1000, "OK", NULL);
    }
    if (cfg->password) {
        sendf(h, "AT+MQTTCFG=\"passwd\",%d,\"%s\"\r", cfg->connect_id, cfg->password);
        wait_for(h, 1000, "OK", NULL);
    }
    if (cfg->reconn_interval_s > 0) {
        int times = cfg->reconn_times;
        if (times == 0) times = 1; // 按需求调整
        sendf(h, "AT+MQTTCFG=\"reconn\",%d,%d,%d\r", times, cfg->reconn_interval_s, 1);
        wait_for(h, 1000, "OK", NULL);
    }
    return 0;
}

int ml307g_mqtt_connect(ml307g_t *h, const char *host, uint16_t port) {
    // 手册示例：+MQTTCONN=<id>,"host",port[,"clientID","user","passwd"]
    if (h->mqtt.client_id || h->mqtt.username || h->mqtt.password)
        sendf(h, "AT+MQTTCONN=%d,\"%s\",%u,\"%s\",\"%s\",\"%s\"\r", h->mqtt.connect_id, host, port,
        h->mqtt.client_id?h->mqtt.client_id:"",
        h->mqtt.username?h->mqtt.username:"",
        h->mqtt.password?h->mqtt.password:"");
    else
        sendf(h, "AT+MQTTCONN=%d,\"%s\",%u\r", h->mqtt.connect_id, host, port);


    // 连接结果通常通过 +MQTTURC:"conn",<id>,<state> 上报，这里等待 URC 或 OK
    int r = wait_for(h, 10000, "+MQTTURC: \"conn\"", "OK");
    if (r==0) h->mqtt_ready = 1;
    return r;
}


int ml307g_mqtt_sub(ml307g_t *h, const char *topic, int qos) {
    sendf(h, "AT+MQTTSUB=%d,\"%s\",%d\r", h->mqtt.connect_id, topic, qos);
    return wait_for(h, 3000, "OK", "+MQTTURC: \"sub\"");
}

int ml307g_mqtt_unsub(ml307g_t *h, const char *topic) {
    sendf(h, "AT+MQTTUNSUB=%d,\"%s\"\r", h->mqtt.connect_id, topic);
    return wait_for(h, 3000, "OK", "+MQTTURC: \"unsub\"");
}


int ml307g_mqtt_pub(ml307g_t *h, const char *topic, const uint8_t *payload, size_t len, int qos, int retain) {
    // 简化：一次性发布。若手册支持长度+二进制数据，亦可改成两步（发送长度后再发负载）
    // 常见格式：AT+MQTTPUB=<id>,"topic",qos,retain,"payload"
    // 对于二进制，请使用 HEX 或 base64，自行在外层封装。
    char msg[256];
    size_t mlen = len;
    if (mlen > 180) mlen = 180; // 防爆缓冲
    for (size_t i = 0; i < mlen; i++) msg[i] = (payload[i] >= 32 && payload[i] < 127) ? payload[i] : '.'; // 简单可视化
    msg[mlen] = '\0';
    sendf(h, "AT+MQTTPUB=%d,\"%s\",%d,%d,\"%s\"\r", h->mqtt.connect_id, topic, qos, retain, msg);
    return wait_for(h, 5000, "OK", "+MQTTURC: \"pub\"");
}


int ml307g_mqtt_read(ml307g_t *h) {
    sendf(h, "AT+MQTTREAD=%d\r", h->mqtt.connect_id);
    return wait_for(h, 2000, "+MQTTURC: \"recv\"", "OK");
}


int ml307g_mqtt_state(ml307g_t *h) {
    sendf(h, "AT+MQTTSTATE=%d\r", h->mqtt.connect_id);
    return wait_for(h, 2000, "+MQTTSTATE:", "OK");
}


int ml307g_mqtt_disc(ml307g_t *h) {
    sendf(h, "AT+MQTTDISC=%d\r", h->mqtt.connect_id);
    int r = wait_for(h, 3000, "OK", "+MQTTURC: \"disc\"");
    if (r == 0) h->mqtt_ready = 0;
    return r;
}


// ---- UART 行解析（支持 CRLF 结束），触发回调
//+MQTTURC: "recv",0,0,"node/soil/cmd","pump_on"
static void parse_line(ml307g_t *h, const char *s) {
    // 典型 URC 样例：
    // +MQTTURC: "conn",<id>,<state>                        //连接状态
    // +MQTTURC: "recv",<id>,<qos>,"topic","payload"        //收到服务器下发消息
    // +MQTTURC: "pub",<id>,<pktid>,<result>                //发布确认
    if (strstr(s, "+MQTTURC:")) {
        if (strstr(s, "\"conn\"")) {
            int id = 0, st = 0;
            sscanf(s, "+MQTTURC: \"conn\",%d,%d", &id, &st);
            if (h->on_connected) h->on_connected(st);
        } else if (strstr(s, "\"recv\"")) {
            // 简化解析：提取 qos、topic、payload（注意真实产品需健壮的 CSV/引号解析）
            int id = 0, qos = 0;
            char topic[128] = {0}, payload[192] = {0};
            // 示例：+MQTTURC: "recv",0,0,"t/a","hello"
            const char *p = strchr(s, ','); // after recv
            if (p) sscanf(p, ",%d,%d,\"%127[^\"]\",\"%191[^\"]\"", &id, &qos, topic, payload);
            if (h->on_msg) h->on_msg(topic, (const uint8_t *) payload, strlen(payload), qos);
        } else if (strstr(s, "\"pub\"")) {
            int id = 0, pktid = 0, result = 0;
            sscanf(s, "+MQTTURC: \"pub\",%d,%d,%d", &id, &pktid, &result);
            if (h->on_puback) h->on_puback(pktid);
        }
    }
}


void ml307g_feed_byte(ml307g_t *h, uint8_t ch) {
    if (ch == '\r') return; // 过滤 CR
    if (ch == '\n') {
        h->line[h->line_len] = 0;
        if (h->line_len > 0) parse_line(h, h->line);
        // 为 wait_for 保留历史（简单起见：累计，生产中请做 ringbuffer/限长）
        size_t L = strlen(h->line);
        if (L > 0 && (L + 2 + strlen(h->line)) < sizeof(h->line)) { strcat(h->line, "\n"); }
        h->line_len = 0;
        h->line[0] = 0;
    } else {
        if (h->line_len < sizeof(h->line) - 1) h->line[h->line_len++] = ch;
    }
}
